package com.ctl.utils;

import lombok.extern.slf4j.Slf4j;
import org.bson.types.ObjectId;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.PropertyAccessorFactory;
import org.springframework.util.StringUtils;

import java.beans.PropertyDescriptor;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>Title: ObjectIdUtil</p>
 * <p>Description: </p>
 * <p>Copyright: Copyright (c) 2019</p>
 * <p>Company: www.ctl.com</p>
 *
 * @author ctl
 * @version 1.1
 * @date 2024-11-19 11:02
 */
@Slf4j
public class ObjectIdUtil {
    /**
     * 支持ObjectId类型和String类型的拷贝
     *
     * @param source
     * @param target
     */
    public static void copyProperties(Object source, Object target, String... ignoreProperties) {
        Map<String, String> map = new HashMap<>();
        Map<String, String> ignorePropertiesMap = new HashMap<>();
        BeanWrapper srcWrapper = PropertyAccessorFactory.forBeanPropertyAccess(source);
        BeanWrapper trgWrapper = PropertyAccessorFactory.forBeanPropertyAccess(target);
        try {
            for (PropertyDescriptor descriptor : srcWrapper.getPropertyDescriptors()) {
                if (descriptor.getPropertyType().getName().equals(ObjectId.class.getName())) {
                    map.put(descriptor.getName(), "");
                }
            }
            for (PropertyDescriptor descriptor : trgWrapper.getPropertyDescriptors()) {
                if (descriptor.getPropertyType().getName().equals(ObjectId.class.getName())) {
                    map.put(descriptor.getName(), "");
                }
            }
            if (ignoreProperties != null) {
                for (String ignoreProperty : ignoreProperties) {
                    if (StringUtils.hasText(ignoreProperty)) {
                        map.put(ignoreProperty, "");
                        ignorePropertiesMap.put(ignoreProperty, "");
                    }
                }
            }
            BeanUtils.copyProperties(source, target, map.keySet().toArray(new String[]{}));
        } catch (Exception e) {
            log.error("", e);
        }
        for (PropertyDescriptor descriptor : srcWrapper.getPropertyDescriptors()) {
            try {
                String propertyName = descriptor.getName();
                if (trgWrapper.isWritableProperty(propertyName) && ignorePropertiesMap.get(propertyName) == null) {
                    Object value = srcWrapper.getPropertyValue(propertyName);
                    if (value instanceof ObjectId && Objects.equals(trgWrapper.getPropertyType(propertyName), String.class)) {
                        trgWrapper.setPropertyValue(propertyName, value.toString());
                    } else if (value instanceof String && Objects.equals(trgWrapper.getPropertyType(propertyName), ObjectId.class)) {
                        trgWrapper.setPropertyValue(propertyName, new ObjectId(value.toString()));
                    }
                }
            } catch (Exception e) {
                log.error("", e);
            }
        }
    }
    /**
     * 支持ObjectId类型和String类型的拷贝
     *
     * @param source
     * @param target
     */
    public static void copyProperties(Object source, Object target) {
        copyProperties(source, target, "");
    }

    public static String objIdToStr(ObjectId objId) {
        return objId == null ? null : objId.toHexString();
    }

    public static Collection<String> objIdToStr(Collection<ObjectId> objIds) {
        return objIds == null ? null : objIds.stream().map(ObjectId::toHexString).collect(Collectors.toList());
    }

    public static ObjectId idStrToObjId(String idStr) {
        return idStr == null ? null : new ObjectId(idStr);
    }

    public static Collection<ObjectId> idStrToObjId(Collection<String> idStrs) {
        return idStrs == null ? null : idStrs.stream().map(ObjectId::new).collect(Collectors.toList());
    }


//    public static void main(String[] args) {
//        A a = new A();
//        a.setId(new ObjectId());
//        a.setName("1");
//        a.setBid(new ObjectId().toString());
//        B b = new B();
//        copyProperties(a, b,"name");
//        System.out.println(b);
//        a = new A();
//        copyProperties(b, a);
//        System.out.println(a);
//    }
}
